package com.zhongen.wflow.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhongen.admin.api.entity.SysDept;
import com.zhongen.admin.api.entity.SysUser;
import com.zhongen.admin.api.entity.SysUserDept;
import com.zhongen.wflow.bean.do_.DeptDo;
import com.zhongen.wflow.bean.do_.RoleDo;
import com.zhongen.wflow.bean.do_.UserDeptDo;
import com.zhongen.wflow.bean.do_.UserDo;
import com.zhongen.wflow.bean.entity.*;
import com.zhongen.wflow.bean.vo.ModelGroupVo;
import com.zhongen.wflow.bean.vo.OrgTreeVo;
import com.zhongen.wflow.bean.vo.UserVo;
import com.zhongen.wflow.mapper.*;
import com.zhongen.wflow.service.OrgRepositoryService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 默认wflow的实现，集成自有系统需要自行实现接口
 *
 * @author : willian fu
 * @date : 2022/11/29
 */
@Service
public class DefaultOrgRepositoryServiceImpl implements OrgRepositoryService {

	@Autowired
	private WflowUsersMapper usersMapper;

	@Autowired
	private WflowRolesMapper rolesMapper;

	@Autowired
	private WflowDepartmentsMapper departsMapper;

	@Autowired
	private WflowUserDepartmentsMapper userDepartmentsMapper;

	@Autowired
	private WflowUserRolesMapper userRolesMapper;

	@Autowired
	private WflowModelPermsMapper modelPermsMapper;

	@Override
	public List<ModelGroupVo.Form> getModelsByPerm(String userId) {
		return modelPermsMapper.selectByPerms(userId);
	}

	@Override
	public UserDo getUserById(String userId) {
		SysUser wflowUsers = usersMapper.selectById(userId);
		if (Objects.nonNull(wflowUsers)) {
			UserDo userDo = new UserDo();
			BeanUtils.copyProperties(wflowUsers, userDo);
			return userDo;
		}
		return null;
	}

	@Override
	public List<OrgTreeVo> selectUsersByPy(String py) {
		return usersMapper.selectUsersByPy(py);
	}

	@Override
	public List<OrgTreeVo> selectUsersByDept(String deptId) {
		return usersMapper.selectUsersByDept(deptId);
	}

	@Override
	public List<UserDo> getUsersBatch(Collection<String> userIds) {
		try {
			return usersMapper.selectBatchIds(userIds)
				.stream()
				.map(u -> new UserDo(u.getUserId(), u.getName(), u.getAvatar(), u.getPhone(), u.getNickname(),
						u.getSex(), u.getPy(), u.getPinyin(), u.getNickname(), u.getEmail()))
				.collect(Collectors.toList());
		}
		catch (Exception e) {
			return Collections.emptyList();
		}
	}

	@Override
	public Set<String> getUsersByDepts(Collection<String> deptIds) {
		try {
			return userDepartmentsMapper
				.selectList(new LambdaQueryWrapper<SysUserDept>().select(SysUserDept::getUserId)
					.in(SysUserDept::getDeptId, deptIds))
				.stream()
				.map(e -> String.valueOf(e.getUserId()))
				.collect(Collectors.toSet());
		}
		catch (Exception e) {
			return Collections.emptySet();
		}
	}

	@Override
	public SysDept getDeptById(String deptId) {
		return departsMapper.selectById(deptId);
	}

	@Override
	public List<DeptDo> getSysAllDepts() {
		try {
			return departsMapper.selectList(null)
				.stream()
				.map(d -> new DeptDo(String.valueOf(d.getDeptId()), d.getName(), d.getLeader(),
						String.valueOf(d.getParentId())))
				.collect(Collectors.toList());
		}
		catch (Exception e) {
			return Collections.emptyList();
		}
	}

	@Override
	public List<UserDeptDo> getSysAllUserDepts() {
		try {
			return userDepartmentsMapper.selectList(null)
				.stream()
				.map(d -> new UserDeptDo(d.getUserId(), d.getDeptId()))
				.collect(Collectors.toList());
		}
		catch (Exception e) {
			return Collections.emptyList();
		}
	}

	@Override
	public List<OrgTreeVo> getSubDeptById(String parentId) {
		return departsMapper.selectByDept(parentId);
	}

	@Override
	public List<String> getRecursiveSubDept(String parentId) {
		List<String> list = new ArrayList<>();
		loadSubDept(parentId, list);
		return list;
	}

	/**
	 * 递归加载所有子部门
	 * @param parentId 父部门ID
	 * @param subDepts 所有子部门缓存
	 */
	private void loadSubDept(String parentId, List<String> subDepts) {
		List<SysDept> departments = departsMapper
			.selectList(new LambdaQueryWrapper<SysDept>().eq(SysDept::getParentId, parentId));
		subDepts.addAll(
				departments.stream().map(SysDept -> String.valueOf(SysDept.getDeptId())).collect(Collectors.toList()));
		departments.forEach(d -> loadSubDept(String.valueOf(d.getDeptId()), subDepts));
	}

	@Override
	public List<RoleDo> getSysAllRoles() {
		try {
			return rolesMapper.selectList(null)
				.stream()
				.map(r -> new RoleDo(String.valueOf(r.getRoleId()), r.getRoleName()))
				.collect(Collectors.toList());
		}
		catch (Exception e) {
			return Collections.emptyList();
		}
	}

	@Override
	public Set<String> getUsersByRoles(List<String> roles) {
		return userRolesMapper
			.selectList(new LambdaQueryWrapper<WflowUserRoles>().select(WflowUserRoles::getUserId)
				.in(WflowUserRoles::getRoleId, roles))
			.stream()
			.map(WflowUserRoles::getUserId)
			.collect(Collectors.toSet());
	}

	@Override
	public String getUserSign(String userId) {
		return usersMapper.selectById(userId).getSign();
	}

	@Override
	public void updateUserSign(String userId, String signature) {
		SysUser sysUser = new SysUser();
		sysUser.setUserId(Long.valueOf(userId));
		sysUser.setSign(signature);
		usersMapper.updateById(sysUser);
	}

	@Override
	public UserVo getUserDetail(String userId) {
		SysUser user = usersMapper.selectById(userId);
		List<SysDept> depts = getDeptsByUser(userId);
		List<WflowRoles> roles = rolesMapper.getRolesByUser(userId);
		return UserVo.builder()
			.userId(userId)
			.username(user.getUsername())
			.sex(user.getSex())
			.avatar(user.getAvatar())
			.entryDate(user.getEntryDate())
			.leaveDate(user.getLeaveDate())
			.positions(Collections.emptyList())
			.depts(depts.stream().map(SysDept::getName).collect(Collectors.toList()))
			.roles(roles.stream().map(WflowRoles::getRoleName).collect(Collectors.toList()))
			.build();
	}

	@Override
	public List<SysDept> getDeptsByUser(String userId) {
		return userDepartmentsMapper.getUserDepts(userId);
	}

}
